#include "selfAdaptionSkin.h"


selfAdaptionSkin::~selfAdaptionSkin(void)
{
}

void selfAdaptionSkin::skinDetectLC(const Mat& _img, Mat& _mask)const
{
	int i, j;
	uchar* imgData = (uchar*)_img.data;
	uchar* maskData = (uchar*)_mask.data;
	for(i = 0; i < _img.rows; i++)
	{
		for (j = 0; j < _img.cols; j++)
		{
			if (1

				&& BGhmin * ((int)imgData[(i * _img.cols + j) * 3 + 1]) + 
				BRminBest * ((int)imgData[(i * _img.cols + j) * 3 + 2]) < 
				((int)imgData[(i * _img.cols + j) * 3])

				&& ((int)imgData[(i * _img.cols + j) * 3]) <
				BGhmax * ((int)imgData[(i * _img.cols + j) * 3 + 1]) +
				BRmaxBest * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&& BGvmin * ((int)imgData[(i * _img.cols + j) * 3]) + 
				GRminBest * ((int)imgData[(i * _img.cols + j) * 3 + 2]) <
				((int)imgData[(i * _img.cols + j) * 3 + 1])

				&& ((int)imgData[(i * _img.cols + j) * 3 + 1]) <
				BGvmax * ((int)imgData[(i * _img.cols + j) * 3]) +
				GRmaxBest * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&&(int)imgData[(i * _img.cols + j) * 3 + 2] >
				50
				)
			{
				maskData[i * _mask.cols + j] = (uchar)255;
			}

		}
	}
	
}

const float selfAdaptionSkin::findFitnessMask(const Mat& _img, const Mat& _mask,
	const float&_BRmin, const float&_BRmax, 
	const float&_GRmin, const float&_GRmax)const
{

	int i, j;
	int areaOfMask = 0;
	float skinMaskCount = 0;
	float BGMaskCount = 0;
	uchar*imgData = (uchar*)_img.data;
	uchar*maskData = (uchar*)_mask.data;
	for (i = 0; i < _img.rows; i++)
	{
		for (j = 0; j < _img.cols; j++)
		{
			if (1

				&& BGhmin * ((int)imgData[(i * _img.cols + j) * 3 + 1]) + 
				_BRmin * ((int)imgData[(i * _img.cols + j) * 3 + 2]) < 
				((int)imgData[(i * _img.cols + j) * 3])

				&& ((int)imgData[(i * _img.cols + j) * 3]) <
				BGhmax * ((int)imgData[(i * _img.cols + j) * 3 + 1]) +
				_BRmax * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&& BGvmin * ((int)imgData[(i * _img.cols + j) * 3]) + 
				_GRmin * ((int)imgData[(i * _img.cols + j) * 3 + 2]) <
				((int)imgData[(i * _img.cols + j) * 3 + 1])

				&& ((int)imgData[(i * _img.cols + j) * 3 + 1]) <
				BGvmax * ((int)imgData[(i * _img.cols + j) * 3]) +
				_GRmax * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&&(int)imgData[(i * _img.cols + j) * 3 + 2] >
				50
				)
			{
				if ((int)(maskData[i *_mask.cols + j]) > 0)
				{
					skinMaskCount = skinMaskCount + 1;
					areaOfMask++;
				}
				else
				{
					BGMaskCount = BGMaskCount + 1;
				}
			}
			else if ((int)(maskData[i * _mask.cols + j]) > 0)
			{
				areaOfMask++;
			}
		}
	}
	float fiter = 2 * skinMaskCount / areaOfMask - 
		BGMaskCount / ((float)(_img.rows * _img.cols - areaOfMask));
	return fiter;
}

const float selfAdaptionSkin::findFitnessROI(const Mat& _img, const Rect& _ROI,
	const float&_BRmin, const float&_BRmax, 
	const float&_GRmin, const float&_GRmax)const
{
	int i, j;
	float skinMaskCount = 0;
	float BGMaskCount = 0;
	uchar*imgData = (uchar*)_img.data;
	for (i = 0; i < _img.rows; i++)
	{
		for (j = 0; j < _img.cols; j++)
		{
			if (1

				&& BGhmin * ((int)imgData[(i * _img.cols + j) * 3 + 1]) + 
				_BRmin * ((int)imgData[(i * _img.cols + j) * 3 + 2]) < 
				((int)imgData[(i * _img.cols + j) * 3])

				&& ((int)imgData[(i * _img.cols + j) * 3]) <
				BGhmax * ((int)imgData[(i * _img.cols + j) * 3 + 1]) +
				_BRmax * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&& BGvmin * ((int)imgData[(i * _img.cols + j) * 3]) + 
				_GRmin * ((int)imgData[(i * _img.cols + j) * 3 + 2]) <
				((int)imgData[(i * _img.cols + j) * 3 + 1])

				&& ((int)imgData[(i * _img.cols + j) * 3 + 1]) <
				BGvmax * ((int)imgData[(i * _img.cols + j) * 3]) +
				_GRmax * ((int)imgData[(i * _img.cols + j) * 3 + 2])

				&&(int)imgData[(i * _img.cols + j) * 3 + 2] >
				50
				)
			{
				if (i >= _ROI.y && i < (_ROI.y + _ROI.height) && j >= _ROI.x && (j < _ROI.x + _ROI.width))
				{
					skinMaskCount = skinMaskCount + 1;
				}
				else
				{
					BGMaskCount = BGMaskCount + 1;
				}
			}
		}
	}
	float fiter = 2 * skinMaskCount / ((float)(_ROI.width * _ROI.height)) - 
		BGMaskCount / ((float)(_img.rows * _img.cols - _ROI.width * _ROI.height));
	return fiter;
}


void selfAdaptionSkin::getBestParamentMask(const Mat& _img, const Mat& _mask)
{
	int i, j;
	float bestPara;

	int bestIdx = 0;
	bestPara = -1000;
	for (i = 0; i < 21; i++)
	{
		BRminBest = BRmin + 0.01 * i - 0.1;
		float tmpFit = findFitnessMask(_img, _mask,
			BRminBest, BRmax, GRmin, GRmax);
		if (bestPara < tmpFit)
		{
			bestPara = tmpFit;
			bestIdx = i;
		}
	}
	BRminBest = BRmin + 0.01 * bestIdx - 0.1;
//	cout<<BRminBest<<ends;

	bestPara = -1000;
	for (i = 0; i < 21; i++)
	{
		BRmaxBest = BRmax + 0.01 * i - 0.1;
		float tmpFit = findFitnessMask(_img, _mask,
			BRminBest, BRmaxBest, GRmin, GRmax);
		if (bestPara < tmpFit)
		{
			bestPara = tmpFit;
			bestIdx = i;
		}
	}
	BRmaxBest = BRmax + 0.01 * bestIdx - 0.1;
//	cout<<BRmaxBest<<ends;

	bestPara = -1000;
	for (i = 0; i < 21; i++)
	{
		GRminBest = GRmin + 0.01 * i - 0.1;
		float tmpFit = findFitnessMask(_img, _mask,
			BRminBest, BRmaxBest, GRminBest, GRmax);
		if (bestPara < tmpFit)
		{
			bestPara = tmpFit;
			bestIdx = i;
		}
	}
	GRminBest = GRmin + 0.01 * bestIdx - 0.1;
//	cout<<GRminBest<<ends;

	bestPara = -1000;
	for (i = 0; i < 21; i++)
	{
		GRmaxBest = GRmax + 0.01 * i - 0.1;
		float tmpFit = findFitnessMask(_img, _mask,
			BRminBest, BRmaxBest, GRminBest, GRmaxBest);
		if (bestPara < tmpFit)
		{
			bestPara = tmpFit;
			bestIdx = i;
		}
	}
	GRmaxBest = GRmax + 0.01 * bestIdx - 0.1;
//	cout<<GRmaxBest<<endl;

}

void selfAdaptionSkin::getBestParamentROI(const Mat& _img, const Rect& _ROI)
{
	int i, j;
	float bestPara;
	int bestIdx = 0;
	bestPara = -1000;
	for (i = 0; i < 21; i++)
	{
		BRminBest = BRmin + 0.01 * i - 0.1;
		float tmpFit = findFitnessROI(_img, _ROI,
			BRminBest, BRmax, GRmin, GRmax);
		if (bestPara < tmpFit)
		{
			bestPara = tmpFit;
			bestIdx = i;
		}
	}
	BRminBest = BRmin + 0.01 * bestIdx - 0.1;
//	cout<<BRminBest<<ends;

	bestPara = -1000;
	for (i = 0; i < 21; i++)
	{
		BRmaxBest = BRmax + 0.01 * i - 0.1;
		float tmpFit = findFitnessROI(_img, _ROI,
			BRminBest, BRmaxBest, GRmin, GRmax);

		if (bestPara < tmpFit)
		{
			bestPara = tmpFit;
			bestIdx = i;
		}
	}
	BRmaxBest = BRmax + 0.01 * bestIdx - 0.1;
//	cout<<BRmaxBest<<ends;

	bestPara = -1000;
	for (i = 0; i < 21; i++)
	{
		GRminBest = GRmin + 0.01 * i - 0.1;
		float tmpFit = findFitnessROI(_img, _ROI,
			BRminBest, BRmaxBest, GRminBest, GRmax);

		if (bestPara < tmpFit)
		{
			bestPara = tmpFit;
			bestIdx = i;
		}
	}
	GRminBest = GRmin + 0.01 * bestIdx - 0.1;
//	cout<<GRminBest<<ends;

	bestPara = -1000;
	for (i = 0; i < 21; i++)
	{
		GRmaxBest = GRmax + 0.01 * i - 0.1;
		float tmpFit = findFitnessROI(_img, _ROI,
			BRminBest, BRmaxBest, GRminBest, GRmaxBest);
		if (bestPara < tmpFit)
		{
			bestPara = tmpFit;
			bestIdx = i;
		}
	}
	GRmaxBest = GRmax + 0.01 * bestIdx - 0.1;
//	cout<<GRmaxBest<<endl;
}